﻿using AppEszköz.Config;
using System;
using System.IO;
namespace AppEszköz.Trace
{
    public class RollingTextTraceListener : TextTraceListener
    {
        private static object rollingLockObject = new object();
        private string fileName;

        private rollOverType rollOverType
        {
            get
            {
                rollOverType rot = rollOverType.MegaByte;
                try
                {
                    string config = ConfigHelper.GetConfig("RollingTextTraceListener.rollOverType");
                    if (config?.Length > 0)
                        rot = (rollOverType)Enum.Parse(typeof(rollOverType), ConfigHelper.GetConfig("RollingTextTraceListener.rollOverType"), true);
                }
                catch
                {
                    // ignored
                }
                return rot;
            }
        }

        private int rollOverConstraint
        {
            get
            {
                int num = 5;
                try
                {
                    string config = ConfigHelper.GetConfig("RollingTextTraceListener.rollOverConstraint");
                    if (config?.Length > 0)
                        num = int.Parse(ConfigHelper.GetConfig("RollingTextTraceListener.rollOverConstraint"));
                }
                catch
                {
                    // ignored
                }
                return num;
            }
        }

        private int filesToKeep
        {
            get
            {
                int num = 10;
                try
                {
                    string config = ConfigHelper.GetConfig("RollingTextTraceListener.FilesToKeep");
                    if (config?.Length > 0)
                        num = int.Parse(ConfigHelper.GetConfig("RollingTextTraceListener.FilesToKeep"));
                }
                catch
                {
                    // ignored
                }
                return num;
            }
        }

        public RollingTextTraceListener(string filename, string name)
          : base(filename, name)
        {
             fileName = filename;
        }

        public RollingTextTraceListener(string filename)
          : base(filename)
        {
             fileName = filename;
        }

        public override void Write(string message)
        {
            lock (RollingTextTraceListener.rollingLockObject)
            {
                if (FileNeedsrollOver())
                    RollOverFile();
            }
            base.Write(message);
            if (filesToKeep < 0)
                return;
             CleanUpArchivedFiles();
        }

        public override void Write(string message, string category)
        {
            lock (RollingTextTraceListener.rollingLockObject)
            {
                if ( FileNeedsrollOver())
                     RollOverFile();
            }
            base.Write(message, category);
            if ( filesToKeep < 0)
                return;
             CleanUpArchivedFiles();
        }

        public override void WriteLine(string message)
        {
            lock (RollingTextTraceListener.rollingLockObject)
            {
                if ( FileNeedsrollOver())
                     RollOverFile();
            }
            base.WriteLine(message);
            if ( filesToKeep < 0)
                return;
             CleanUpArchivedFiles();
        }

        public override void WriteLine(string message, string category)
        {
            lock (RollingTextTraceListener.rollingLockObject)
            {
                if ( FileNeedsrollOver())
                     RollOverFile();
            }
            base.WriteLine(message, category);
            if ( filesToKeep < 0)
                return;
             CleanUpArchivedFiles();
        }

        private bool FileNeedsrollOver()
        {
            bool flag = false;
            string str = RollingTextTraceListener.RootFileName( fileName);
            if (File.Exists(str))
            {
                FileInfo fileInfo = new FileInfo(str);
                switch ( rollOverType)
                {
                    case rollOverType.Minute:
                        if (fileInfo.CreationTime.AddMinutes((double) rollOverConstraint) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.Hour:
                        if (fileInfo.CreationTime.AddHours((double) rollOverConstraint) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.Day:
                        if (fileInfo.CreationTime.AddDays((double) rollOverConstraint) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.Week:
                        if (fileInfo.CreationTime.AddDays((double)( rollOverConstraint * 7)) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.Month:
                        if (fileInfo.CreationTime.AddMonths( rollOverConstraint) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.Year:
                        if (fileInfo.CreationTime.AddYears( rollOverConstraint) < DateTime.Now)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.KiloByte:
                        if (fileInfo.Length >= (long)( rollOverConstraint * 1024))
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.MegaByte:
                        if (fileInfo.Length >= (long)( rollOverConstraint * 1048576))
                        {
                            flag = true;
                            break;
                        }
                        break;
                    case rollOverType.GigaByte:
                        if (fileInfo.Length >= (long)( rollOverConstraint * 1073741824))
                        {
                            flag = true;
                            break;
                        }
                        break;
                }
            }
            return flag;
        }

        private void RollOverFile()
        {
            string str = RollingTextTraceListener.RootFileName( fileName);
            string archiveFilename = RollingTextTraceListener.CreateArchiveFilename(str,  rollOverType);
            try
            {
                 Writer.Flush();
                 Close();
                File.Move(str, archiveFilename);
                new FileStream(str, FileMode.CreateNew).Close();
                File.SetCreationTime(str, DateTime.Now);
                 Writer = (TextWriter)new FileInfo(str).CreateText();
            }
            catch (Exception ex)
            {
                Console.Write("Failed rolling over: {0}{1}{2}", (object)str, (object)Environment.NewLine, (object)ex.Message);
            }
        }

        private void CleanUpArchivedFiles()
        {
            string path = RollingTextTraceListener.RootFileName( fileName);
            string directoryName = Path.GetDirectoryName(path);
            string withoutExtension = Path.GetFileNameWithoutExtension(path);
            string extension = Path.GetExtension(path);
            try
            {
                if (directoryName != null)
                {
                    string[] files = Directory.GetFiles(directoryName, $"{(object) withoutExtension}_*{(object) extension}");
                    if (files.Length <=  filesToKeep)
                        return;
                    Array.Sort<string>(files);
                    for (int index = 0; index < files.Length -  filesToKeep; ++index)
                        File.Delete(Path.Combine(directoryName, files[index]));
                }
            }
            catch (Exception ex)
            {
                Console.Write("Failed deleting files: {0}", (object)ex.Message);
            }
        }

        private static string RootFileName(string fileName)
        {
            string str = fileName;
            if (!Path.IsPathRooted(str))
                str = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, str);
            return str;
        }

        private static string CreateArchiveFilename(string fileName, rollOverType rollOverType)
        {
            string directoryName = Path.GetDirectoryName(fileName);
            string withoutExtension = Path.GetFileNameWithoutExtension(fileName);
            string extension = Path.GetExtension(fileName);
            string str; 
            switch (rollOverType)
            {
                case rollOverType.Minute:
                    str = Path.Combine(directoryName,
                        $"{withoutExtension}{(object) DateTime.Now.ToString("_yyyy_MM_dd_HH_mm")}{(object) extension}");
                    break;
                case rollOverType.Hour:
                    str = Path.Combine(directoryName,
                        $"{(object) withoutExtension}{(object) DateTime.Now.ToString("_yyyy_MM_dd_HH")}{(object) extension}");
                    break;
                case rollOverType.Day:
                    str = Path.Combine(directoryName,
                        $"{(object) withoutExtension}{(object) DateTime.Now.ToString("_yyyy_MM_dd")}{(object) extension}");
                    break;
                case rollOverType.Month:
                    str = Path.Combine(directoryName,
                        $"{(object) withoutExtension}{(object) DateTime.Now.ToString("_yyyy_MM")}{(object) extension}");
                    break;
                case rollOverType.Year:
                    str = Path.Combine(directoryName,
                        $"{(object) withoutExtension}{(object) DateTime.Now.ToString("_yyyy")}{(object) extension}");
                    break;
                default:
                    str = Path.Combine(directoryName,
                        $"{(object) withoutExtension}{(object) DateTime.Now.ToString("_yyyy_MM_dd_HH_mm_ss_fffffff")}{(object) extension}");
                    break;
            }
            return str;
        }
    }
}